package com.jc.repository.generator.plugins;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;

import javax.persistence.Column;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


//@NotNull(message = "小组id不能为空")
//private Integer tid;
//
//@NotNull(message = "市场不能为空")
//@Range(min = 0, max = 9, message = "市场取值不正确")
//private Integer market;
//
//@NotNull(message = "流量类型不能为空")
//@Range(min = 1, max = 3, message = "流量取值不正确")
//private Integer flowtype;
//
//private String sid;
//
//@Length(max = 200, message = "域名长度超出范围")
//@NotBlank(message = "域名不能为空")
//private String domain;
//
//@NotBlank(message = "广告创意尺寸不能为空")
//@Length(max = 100, message = "广告创意尺寸长度超出范围")

/**
 * @author jared
 * @author wangli
 * @Description:自动生成domain对象构建器
 * @date Dec 31, 2014 3:28:40 PM
 * @date 2017年1月8日
 * @Description
 */
public class BuildersPlugin extends PluginAdapter {

    private String STRING = "string";
    private String DATE = "date";
    private String MESSAGE_CANNT_BE_NULL = "不能为空";
    private String MESSAGE_OUT_OF_RANGE = "必须在{min}和{max之间}";
    private String MESSAGE_VALUE_IS_NOT_CORRECT = "取值不正确";

    @Override
    public boolean validate(List<String> warnings) {
        return Boolean.TRUE;
    }

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        generateBuilders(introspectedTable, topLevelClass);
        return Boolean.TRUE;
    }

    @Override
    public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        generateBuilders(introspectedTable, topLevelClass);
        return Boolean.TRUE;
    }

    @Override
    public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        generateBuilders(introspectedTable, topLevelClass);
        return Boolean.TRUE;
    }

    private void generateBuilders(IntrospectedTable introspectedTable, TopLevelClass topLevelClass) {
        List<IntrospectedColumn> columns;
        if (introspectedTable.getRules().generateRecordWithBLOBsClass()) {
            columns = introspectedTable.getNonBLOBColumns();
        } else {
            columns = introspectedTable.getAllColumns();
        }

        List fields = topLevelClass.getFields();
//		for (IntrospectedColumn column : columns) {
        for (Integer i = 0; i < columns.size(); ++i) {

            IntrospectedColumn column = (IntrospectedColumn) columns.get(i);

            String typeName = column.getFullyQualifiedJavaType().toString().toLowerCase();
            Field method = (Field) fields.get(i);
            String originComment = column.getRemarks().replace("：", ":").replace("；", ";");
            String realComment = "";
            if (originComment.contains(":") || originComment.contains("：")) {
                realComment = Lists.newArrayList(Splitter.on(":").omitEmptyStrings().split(originComment)).get(0);

            }else {
                realComment = originComment;
            }
            method.addAnnotation("@Column(name = \"" + column.getActualColumnName() + "\")");
            if (!column.isNullable() && !column.getJavaProperty().equals("id")) {
                if (typeName.contains(STRING)) {
                    method.addAnnotation("@NotBlank(" + "message = \"" + realComment + MESSAGE_CANNT_BE_NULL + "\" )");
                } else {
                    if (!column.isNullable()) {
                        method.addAnnotation("@NotNull(" + "message = \"" + realComment + MESSAGE_CANNT_BE_NULL + "\" )");
                    }

                }

            }

            if (column.getJavaProperty().equals("id")){
                method.addAnnotation("@Id");
                method.addAnnotation("@GeneratedValue(strategy = GenerationType.AUTO)");
            }

//            column.ge

            if (typeName.contains(STRING)){
                method.addAnnotation("@Length(" + "max=" + column.getLength() + ",message = \"" + realComment + MESSAGE_OUT_OF_RANGE + "\")");
            }


            if (typeName.contains(DATE)) {
                method.addAnnotation("@JsonSerialize(using = CustomDateSerializer.class)");
                method.addAnnotation("@JsonDeserialize(using = CustomDateDeserializer.class)");
                method.addAnnotation(" @Temporal(TemporalType.TIMESTAMP)");
            }
//            if (typeName.contains(DATE))

            Method methodAddSetAndGet = new Method();

            methodAddSetAndGet.setVisibility(JavaVisibility.PUBLIC);
            methodAddSetAndGet.setReturnType(new FullyQualifiedJavaType(introspectedTable.getFullyQualifiedTable()
                    .getDomainObjectName()));
            methodAddSetAndGet.setName(column.getJavaProperty());
            methodAddSetAndGet.addParameter(new Parameter(column.getFullyQualifiedJavaType(), "value"));
            methodAddSetAndGet.addBodyLine("this." + column.getJavaProperty() + " = value;");
            methodAddSetAndGet.addBodyLine("return this;");
            topLevelClass.addMethod(methodAddSetAndGet);
        }
        String tableName = introspectedTable.getFullyQualifiedTable().getIntrospectedTableName();


        topLevelClass.addAnnotation("@JsonIgnoreProperties(ignoreUnknown = true)");
        topLevelClass.addAnnotation("@Entity");
        topLevelClass.addAnnotation("@Table(name = \"mgr."+tableName+"\")");
//        topLevelClass.addAnnotation("@DynamicUpdate(true)");
//        topLevelClass.addAnnotation("@DynamicInsert(true)");

        topLevelClass.addImportedType("javax.persistence.Column");
        topLevelClass.addImportedType("javax.validation.constraints.NotNull");
        topLevelClass.addImportedType("com.fasterxml.jackson.annotation.JsonIgnoreProperties");
        topLevelClass.addImportedType("com.fasterxml.jackson.databind.annotation.JsonDeserialize");
        topLevelClass.addImportedType("com.fasterxml.jackson.databind.annotation.JsonSerialize");
        topLevelClass.addImportedType("com.mjoys.common.serializer.CustomDateDeserializer");
        topLevelClass.addImportedType("com.mjoys.common.serializer.CustomDateSerializer");
//        topLevelClass.addImportedType("org.hibernate.annotations.DynamicInsert");
//        topLevelClass.addImportedType("org.hibernate.annotations.DynamicUpdate");
        topLevelClass.addImportedType("org.hibernate.validator.constraints.Length");
        topLevelClass.addImportedType("org.hibernate.validator.constraints.NotBlank");
        topLevelClass.addImportedType("org.hibernate.validator.constraints.Range");

        topLevelClass.addImportedType("javax.persistence.Basic");
        topLevelClass.addImportedType("javax.persistence.Column");
        topLevelClass.addImportedType("javax.persistence.Entity");
        topLevelClass.addImportedType("javax.persistence.GeneratedValue");
        topLevelClass.addImportedType("javax.persistence.GenerationType");
        topLevelClass.addImportedType("javax.persistence.Id");
        topLevelClass.addImportedType("javax.persistence.Table");
        topLevelClass.addImportedType("javax.persistence.Temporal");
        topLevelClass.addImportedType("javax.persistence.TemporalType");
        topLevelClass.addImportedType("javax.validation.constraints.NotNull");
        topLevelClass.addFileCommentLine("/**\n" +
                " * @author wangli\n" +
                " * @create "+new Date()+"\n" +
                " * @description\n" +
                " */");
    }
}
